package com.example.generator.task;

import com.example.generator.config.GenConfig;
import com.example.generator.domain.GenTable;
import com.example.generator.domain.GenTableColumn;
import com.example.generator.mapper.GenTableColumnMapper;
import com.example.generator.service.IGenTableService;
import com.example.generator.util.*;
import io.jsonwebtoken.lang.Collections;
import org.apache.commons.io.FileUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;

@Component
@Order(value = 1)
public class GenCodeTask implements CommandLineRunner {

    @Autowired
    private IGenTableService genTableService;

    @Autowired
    private GenTableColumnMapper genTableColumnMapper;


    @Override
    public void run(String... strings) throws Exception {
        System.out.println(">>>>>>>>>>>>>>>服务启动执行，执行代码生成操作 <<<<<<<<<<<<<");
        genCode();
        System.out.println(">>>>>>>>>>>>>>>服务启动执行，执行代码生成操作完成 <<<<<<<<<<<<<");
        System.exit(0);
    }


    /**
     * 获取表信息
     */
    public void genCode() {
        String tables = GenConfig.tableName;
        String[] tableNames = Convert.toStrArray(tables);
        // 查询表信息
        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
        // 初始化表和字段信息
        initGenTableInfo(tableList);
        for (GenTable table : tableList) {
            generatorCode(table);
        }
    }


    /**
     * 初始化表和字段信息
     *
     * @param tableList
     * @return
     */
    public void initGenTableInfo(List<GenTable> tableList) {
        for (GenTable table : tableList) {
            String tableName = table.getTableName();
            GenUtils.initTable(table, GenConfig.author);
            List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
            for (GenTableColumn column : genTableColumns) {
                GenUtils.initColumnField(column, table);
            }
            table.setColumns(genTableColumns);
        }
    }


    /**
     * 生成代码（自定义路径）
     *
     * @param table
     */
    public void generatorCode(GenTable table) {

        // 设置主键列信息
        setPkColumn(table);
        //设置velocity资源加载器
        VelocityInitializer.initVelocity();
        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            try {
                String path = getGenPath(table, template);
                System.out.println("生成路径：" + path);
                FileUtils.writeStringToFile(new File(path), sw.toString(), "UTF-8");
            } catch (IOException e) {
                //throw new ServiceException("渲染模板失败，表名：" + table.getTableName());
            }
        }
    }


    /**
     * 设置主键列信息
     *
     * @param table 业务表信息
     */
    public void setPkColumn(GenTable table) {
        for (GenTableColumn column : table.getColumns()) {
            if (column.isPk()) {
                table.setPkColumn(column);
                break;
            }
        }
        if (StringUtils.isNull(table.getPkColumn()) && !Collections.isEmpty(table.getColumns())) {
            table.setPkColumn(table.getColumns().get(0));
        }
    }

    /**
     * 获取代码生成地址
     *
     * @param table    业务表信息
     * @param template 模板文件路径
     * @return 生成地址
     */
    public static String getGenPath(GenTable table, String template) {
        String genPath = GenConfig.getGenPath();
        return System.getProperty("user.dir") + genPath + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
    }


}
